package com.itheima.d1_junit;

import org.junit.*;

/**
 * 测试类
 *  Java高级技术:单元测试，反射，注解，动态代理
 *        磊哥说：这些技术都学完，那么整个javase就齐全了，大家下一阶段就可以正式进入到Java企业级开发或者说Java框架的学习了
 *        视频里面用的ppt和现在的给的ppt是不一样的，应该是黑马疏忽了。新课程里面的新ppt，在文字说明上面比现在手上旧的好太多了
 *
 * 单元测试：
 *      单元测试就是针对最小的功能单元(方法)，编写测试代码对该功能进行正确性测试。
 *
 * 目前测试方法是怎么进行的？ 存在什么问题 ？
 * 只能编写main方法，并在main方法中再去调用其他方法进行测试。
 * 使用起来很不灵活，无法实现自动化测试。
 * 无法得到测试的报告，需要程序员自己去观察测试是否成功。
 *
 * Junit单元测试框架:
 * JUnit是使用Java语言实现的单元测试框架，它是第三方公司开源出来的，很多开发工具已经集成了Junit框架，比如IDEA。
 * 优点
 * 编写的测试代码很灵活，可以针对某个方法执行测试，也支持一键完成自动化测试。
 * 不需要程序员去分析测试的结果，会自动生成测试报告出来。
 * 提供了更强大的测试能力。
 *
 * Junit单元测试-快速入门:
 * 某个系统，有多个业务方法，请使用Junit框架完成对这些方法的单元测试。
 * 具体步骤
 * 将Junit框架的jar包导入到项目中（注意：IDEA集成了Junit框架，不需要我们自己手工导入了）
 * 为需要测试的业务类，定义对应的测试类，并为每个业务方法编写对应的测试类方法
 * （注意：测试方法必须是公共的，无参数，无返回值的非静态方法）
 * 必须在测试方法上使用@Test注解（标注该方法是一个测试方法）
 * 在测试方法中编写程序，调用被测试的业务方法即可。
 * 开始测试：选中测试方法，右键选择“JUnit运行” ，如果测试通过则是绿色；如果测试失败，则是红色
 *
 * Junit单元测试是做什么的？
 * 测试类中方法的正确性的。
 * Junit单元测试的优点是什么？
 * JUnit可以选择执行哪些测试方法，可以一键执行全部测试方法的测试。
 *  JUnit可以生测试报告，如果测试良好则是绿色；如果测试失败，则是红色。
 * 单元测试中的某个方法测试失败了，不会影响其他测试方法的测试。
 *
 *
 * Junit单元测试框架的常用注解(Junit 4.xxxx版本)
 *   注解             说明
 * @Test            测试方法
 * @Before          用来修饰一个实例方法，该方法会在每一个测试方法执行之前执行一次。
 * @After           用来修饰一个实例方法，该方法会在每一个测试方法执行之后执行一次。
 * @BeforeClass     用来修饰一个静态方法，该方法会在所有测试方法执行之前只执行一次。
 * @AfterClass      用来修饰一个静态方法，该方法会在所有测试方法执行完之后只执行一次。
 * 在测试方法执行器执行的方法，常用于：初始化资源
 * 在测试方法执行完后再执行的方法，常用于：释放资源
 *
 * Junit单元测试框架的常用注解(Junit 5.xxxx版本)
 *   注解               说明
 * @Test             测试方法
 * @BeforeEach       用来修饰一个实例方法，该方法会在每一个测试方法执行之前执行一次。
 * @AfterEach        用来修饰一个实例方法，该方法会在每一个测试方法执行之后执行一次。
 * @BeforeAll        用来修饰一个静态方法，该方法会在所有测试方法之前只执行一次。
 * @AfterAll         用来修饰一个静态方法，该方法会在所有测试方法之后只执行一次。
 *
 * 开始执行的方法:初始化资源。
 * 执行完之后的方法:释放资源。
 */

public class StringUtilTest {
    /*
   假设每个测试的实例方法，都需要独立的通信管道，那么这个通信管道可以定义在实例方法前面，就可以在@Before注解对应的方法里面进行初始化
   在@After注解对应的方法里面进行通信管道资源的释放

   假设这些测试方法要公用同一个通信管道，那就定义一个静态的通信管道private static Socket socket;
   然后把这个通信管道在@BeforeClass注解修饰的静态方法里面进行初始化
   然后在@AfterClass里面关闭管道
    */
    @Before
    public void test1(){
        System.out.println("---> test1 Before 执行了---------");
    }

    @BeforeClass
    public static void test11(){
        System.out.println("---> test11 BeforeClass 执行了---------");
    }

    @After
    public void test2(){
        System.out.println("---> test2 After 执行了---------");
    }

    @AfterClass
    public static void test22(){
        System.out.println("---> test22 AfterClass 执行了---------");
    }

    @Test // 测试方法
    public void testPrintNumber(){
        StringUtil.printNumber("admin");
        StringUtil.printNumber(null);


    }

    @Test // 测试方法
    public void testGetMaxIndex(){
        int index1 = StringUtil.getMaxIndex(null);
        System.out.println(index1);

        int index2 = StringUtil.getMaxIndex("admin");
        //这里的测试结果是没有问题的，绿色的，那测试方法认为这个业务方法里面是没有bug，只要这个方法内部没有出现异常，测试方法就认为这个业务方法时正确的
        //但是实际上，业务方法中说的是求索引值，而业务方法中返回的是字符串的长度，所以测试方法未检测出来业务方法中的功能问题
        System.out.println(index2);

        /*
        所以Junit单元测试框架提供了断言机制，断言机制：程序员可以通过预测业务方法的结果。assertEquals有很多重载的方法，用下面这个：
        源码：public static void assertEquals(String message, long expected, long actual)
        第一个参数：假若实际值和预测值不同，提示错误      第二个参数：我们预测的方法值      第三个参数：方法返回的实际值
         */
        Assert.assertEquals("方法内部有bug!", 4, index2);
    }
}
